import {
  ApiEditorDetailResDto,
  ApiEditorGetReqDto,
} from '../../types/editor.dto';
import { LcDocument, LcProject } from '../../types/editor.type';
import { fixLifeCycleDuplicated } from './fixLifeCycleDuplicated';
import { mergeDefaultUtils } from './mergeDefaultUtils';
import { transformSchemaStyleToCss } from './styleToCss';

export const transformExport = async function (
  res: ApiEditorDetailResDto,
  options: {
    frame?: ApiEditorGetReqDto['frame'];
  },
) {
  const { frame } = options;
  const { project, documents, componentDocs } = JSON.parse(JSON.stringify(res));
  const packages = project.packages?.[frame] || project.packages;
  const packageNames = packages.map((pkg) => pkg.package);
  const ignorePackageNames =
    frame === 'app'
      ? ['moment', 'lodash']
      : ['@alifd/next', 'iconfont-icons', '@alifd/layout'];
  console.log('project.appConfig: ', project.appConfig);
  const packageJSON =
    frame === 'app'
      ? {
          dependencies: {
            '@babel/runtime': '^7.21.5',
            '@tarojs/components': '3.6.22',
            '@tarojs/helper': '3.6.22',
            '@tarojs/plugin-framework-react': '3.6.22',
            '@tarojs/plugin-html': '3.6.22',
            '@tarojs/plugin-platform-alipay': '3.6.22',
            '@tarojs/plugin-platform-jd': '3.6.22',
            '@tarojs/plugin-platform-qq': '3.6.22',
            '@tarojs/plugin-platform-swan': '3.6.22',
            '@tarojs/plugin-platform-tt': '3.6.22',
            '@tarojs/plugin-platform-weapp': '3.6.22',
            '@tarojs/plugin-platform-h5': '3.6.22',
            '@tarojs/react': '3.6.22',
            '@tarojs/rn-runner': '3.6.22',
            '@tarojs/router': '3.6.22',
            '@tarojs/runtime': '3.6.22',
            '@tarojs/shared': '3.6.22',
            '@tarojs/taro': '3.6.22',
            '@tarojs/taro-h5': '3.6.22',
            '@tarojs/taro-rn': '3.6.22',
            'async-validator': '^4.2.5',
            'cross-ui': '^4.0.41',
            'crypto-browserify': '^3.12.0',
            dayjs: '^1.11.6',
            expo: '~46.0.2',
            mobx: '^4.8.0',
            'mobx-react': '^6.1.4',
            react: '^18.0.0',
            'react-dom': '^18.0.0',
            'react-native': '^0.69.3',
            'react-native-svg': '~12.4.3',
            'stream-browserify': '^3.0.0',
          },
        }
      : {
          dependencies: {
            // '@appthen/react': '^1.0.1',
            // '@appthen/antd': '^1.0.1',
            // '@appthen/antd-pro': '^1.0.1',
            // antd: '^5.9.0',
            axios: '^1.4.0',
            history: '4.x',
            react: project.appConfig?.reactVersion === '18' ? '^18' : '^17',
            'react-dom':
              project.appConfig?.reactVersion === '18' ? '^18' : '^17',
            'react-router-dom': '^6.22.3',
            vconsole: '^3.15.1',
            '@appthen/utils': '^1.0.3',
          },
        };
  packages
    .filter((pkg) => !ignorePackageNames.includes(pkg.package))
    .forEach((pkg) => {
      packageJSON.dependencies[pkg.package] = pkg.version;
    });
  // console.log(
  //   'packages: ',
  //   packages.map((pkg) => {
  //     return {
  //       package: pkg.package,
  //       version: pkg.version,
  //     };
  //   }),
  // );
  // console.log('packageNames: ', packageNames);
  project.documents = project.documents.filter((doc: any) => {
    if (frame) return (doc.frames || [project.type]).includes(frame);
    return true;
  });
  const docIds = documents.map((doc: any) => doc._id);
  let componentsTree = componentDocs
    .filter((comp: any) => {
      return !docIds.includes(comp._id);
    })
    .concat(documents);
  componentsTree = filterAndMapDocumentsWithFrame(
    project,
    componentsTree,
    options.frame,
  );
  const componentNames: Record<string, boolean> = {};
  const componentsMap: Record<string, any> = [];
  componentsTree.forEach((doc: any) => {
    if (doc.componentsMap) {
      doc.componentsMap.forEach((item: any) => {
        const k = `${item.package}_${item.componentName}`;
        if (!componentNames[k]) {
          if (packageNames.includes(item.package)) {
            componentNames[k] = true;
            componentsMap.push(item);
          } else {
            // 包被替换掉了，所以packages里面没有，需要用新的包名替换掉
            // 现在先不管，目前最简单的方案就是所有页面保存一次
          }
        }
      });
    } else {
      console.log('页面需要更新: ', doc.title, doc.fileName);
    }
  });
  let schema = {
    ...project.schema,
    componentsMap,
    componentsTree: componentsTree.map((item: any) => {
      const schema =
        typeof item.schema === 'string' ? JSON.parse(item.schema) : item.schema;
      if (schema.componentName === 'Component' && schema.props) {
        delete schema.props.fill;
      }
      return schema;
    }),
  };
  // console.log('componentsMap: ', componentsMap);
  // 默认用 JSONC 的格式解析（兼容 JSON）

  const clientType = options.frame || project.type;
  const isWeb = clientType === 'web';
  const solution = isWeb ? 'vite' : 'taro';

  // 处理route中过滤组件
  const { router } = schema;
  if (router?.routes) {
    const { documents } = project;
    const allComponentNames = documents
      .filter((_) => _.type === 'Component')
      .map((_) => _.fileName);
    const webPageNames = documents
      .filter((_) => _.frames && _.frames.includes('web'))
      .map((_) => _.fileName);
    const exec = function (routes) {
      routes.forEach((route) => {
        if (route.children?.length > 0) {
          route.children = exec(route.children);
        }
      });
      const pageNames = routes.map((_) => _.page);
      return routes.filter(
        (_) => !allComponentNames.includes(_.page) || !!_.children?.length,
      );
    };
    router.routes = exec(router.routes);
  }

  // 补充默认 global utils
  schema = mergeDefaultUtils(schema);

  // 转换Schema生成css
  schema = await transformSchemaStyleToCss(schema, solution);

  // 处理生命周期方法重复问题
  schema = await fixLifeCycleDuplicated(schema);
  return {
    project,
    packageJSON,
    schema: JSON.stringify(schema),
    documents: filterAndMapDocumentsWithFrame(
      project,
      documents,
      options.frame,
    ),
    componentDocs: filterAndMapDocumentsWithFrame(
      project,
      componentDocs,
      options.frame,
    ),
  };
};

const filterAndMapDocumentsWithFrame = (
  project: LcProject,
  documents: LcDocument[],
  frame?: string,
) => {
  return documents
    .filter((doc: any) => {
      if (frame) return (doc.frames || [project.type]).includes(frame);
      return true;
    })
    .map((doc) => {
      // 根据框架加载componentsMap
      if (doc.componentsRoot?.[frame || project.type]) {
        doc.componentsMap = doc.componentsRoot[frame || project.type];
      }
      // if (doc.fileName === 'index') {
      //   console.log('doc.componentsMap: ', doc.componentsMap);
      // }
      return doc;
    });
};
